<<<<<<< HEAD
=======
<!--
 * @Description: 学生管理
 * @Author: charles
 * @Date: 2021-12-19 10:04:20
 * @LastEditors: charles
 * @LastEditTime: 2021-12-19 10:15:54
-->
<template>
  <div class="student-management">
    <div class="control-panel">
      <div class="search-bar">
        <el-input
          v-model="searchForm.keyword"
          placeholder="请输入学生姓名/学号搜索"
          clearable
          prefix-icon="el-icon-search"
          @keyup.enter.native="handleSearch"
        ></el-input>
        <el-button type="primary" @click="handleSearch">查询</el-button>
        <el-button @click="resetSearch">重置</el-button>
        <el-button type="success" icon="el-icon-plus" @click="handleAdd">新增学生</el-button>
      </div>
      
      <div class="filter-options">
        <el-select v-model="searchForm.grade" placeholder="年级" clearable>
          <el-option v-for="item in gradeOptions" :key="item.value" :label="item.label" :value="item.value"></el-option>
        </el-select>
        <el-select v-model="searchForm.major" placeholder="专业" clearable>
          <el-option v-for="item in majorOptions" :key="item.value" :label="item.label" :value="item.value"></el-option>
        </el-select>
      </div>
    </div>

    <!-- 错误提示 -->
    <el-alert
      v-if="fetchError"
      title="获取学生数据失败"
      type="error"
      description="无法从服务器获取学生数据，已显示本地备份数据。"
      show-icon
      :closable="true"
      style="margin-bottom: 15px"
      @close="fetchError = false"
    >
      <template slot="title">
        获取学生数据失败
        <el-button type="text" size="small" @click="retryFetch">重试</el-button>
      </template>
    </el-alert>

    <!-- 学生数据表格 -->
    <el-table
      v-loading="loading"
      :data="studentList"
      border
      stripe
      highlight-current-row
      style="width: 100%"
    >
      <el-table-column prop="id" label="学号" width="120" align="center"></el-table-column>
      <el-table-column prop="name" label="姓名" width="100" align="center"></el-table-column>
      <el-table-column prop="gender" label="性别" width="60" align="center">
        <template slot-scope="scope">
          {{ scope.row.gender === 'M' ? '男' : '女' }}
        </template>
      </el-table-column>
      <el-table-column prop="grade" label="年级" width="100" align="center"></el-table-column>
      <el-table-column prop="major" label="专业" width="150"></el-table-column>
      <el-table-column prop="className" label="班级" width="120" align="center"></el-table-column>
      <el-table-column prop="email" label="邮箱"></el-table-column>
      <el-table-column prop="courseCount" label="已选课程数" width="120" align="center"></el-table-column>
      <el-table-column label="操作" width="240" fixed="right" align="center">
        <template slot-scope="scope">
          <el-button type="text" size="small" @click="handleViewCourses(scope.row)">查看已选课程</el-button>
          <el-button type="text" size="small" @click="handleEdit(scope.row)">编辑</el-button>
          <el-button type="text" size="small" @click="toDetails(scope.row.id)">详情</el-button>
          <el-button type="text" size="small" style="color: #F56C6C" @click="handleDelete(scope.row)">删除</el-button>
        </template>
      </el-table-column>
    </el-table>

    <!-- 分页控件 -->
    <div class="pagination-container">
      <el-pagination
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="pagination.page"
        :page-sizes="[10, 20, 50, 100]"
        :page-size="pagination.pageSize"
        layout="total, sizes, prev, pager, next, jumper"
        :total="pagination.total"
      >
      </el-pagination>
    </div>

    <!-- 新增/编辑学生对话框 -->
    <el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="500px">
      <el-form :model="formData" :rules="formRules" ref="studentForm" label-width="80px">
        <el-form-item label="学号" prop="id">
          <el-input v-model="formData.id" :disabled="isEdit"></el-input>
        </el-form-item>
        <el-form-item label="姓名" prop="name">
          <el-input v-model="formData.name"></el-input>
        </el-form-item>
        <el-form-item label="性别" prop="gender">
          <el-radio-group v-model="formData.gender">
            <el-radio label="M">男</el-radio>
            <el-radio label="F">女</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="年级" prop="grade">
          <el-select v-model="formData.grade" placeholder="请选择年级">
            <el-option v-for="item in gradeOptions" :key="item.value" :label="item.label" :value="item.value"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="专业" prop="major">
          <el-select v-model="formData.major" placeholder="请选择专业">
            <el-option v-for="item in majorOptions" :key="item.value" :label="item.label" :value="item.value"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="班级" prop="className">
          <el-input v-model="formData.className"></el-input>
        </el-form-item>
        <el-form-item label="邮箱" prop="email">
          <el-input v-model="formData.email"></el-input>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="submitForm">确定</el-button>
      </div>
    </el-dialog>

    <!-- 已选课程对话框 -->
    <el-dialog title="已选课程" :visible.sync="coursesDialogVisible" width="800px">
      <el-table :data="selectedCourses" border style="width: 100%">
        <el-table-column prop="courseId" label="课程编号" width="120" align="center"></el-table-column>
        <el-table-column prop="courseName" label="课程名称"></el-table-column>
        <el-table-column prop="credit" label="学分" width="80" align="center"></el-table-column>
        <el-table-column prop="teacherName" label="任课教师" width="120" align="center"></el-table-column>
        <el-table-column prop="selectTime" label="选课时间" width="160" align="center"></el-table-column>
        <el-table-column label="操作" width="120" align="center">
          <template slot-scope="scope">
            <el-button type="text" size="small" style="color: #F56C6C" @click="handleCancelCourse(scope.row)">退选</el-button>
          </template>
        </el-table-column>
      </el-table>
    </el-dialog>
  </div>
</template>

<script>
import { getStudentList, saveOrUpdateStudent, deleteStudent, getStudentCourses, cancelCourse } from '@/api/student'

export default {
  data() {
    return {
      // 搜索表单
      searchForm: {
        keyword: '',
        grade: '',
        major: ''
      },
      // 表格数据
      studentList: [
        {
          id: '20210001',
          name: '张三',
          gender: 'M',
          grade: '2021',
          major: '计算机科学与技术',
          className: '计科2101',
          email: 'zhangsan@example.com',
          courseCount: 3
        },
        {
          id: '20210002',
          name: '李四',
          gender: 'F',
          grade: '2021',
          major: '软件工程',
          className: '软工2101',
          email: 'lisi@example.com',
          courseCount: 2
        },
        {
          id: '20220001',
          name: '王五',
          gender: 'M',
          grade: '2022',
          major: '网络空间安全',
          className: '网安2201',
          email: 'wangwu@example.com',
          courseCount: 4
        }
      ],
      loading: false,
      // 分页参数
      pagination: {
        page: 1,
        pageSize: 10,
        total: 3
      },
      // 对话框控制
      dialogVisible: false,
      dialogTitle: '新增学生',
      isEdit: false,
      // 课程对话框
      coursesDialogVisible: false,
      selectedCourses: [],
      currentStudentId: '',
      // 表单数据
      formData: {
        id: '',
        name: '',
        gender: 'M',
        grade: '',
        major: '',
        className: '',
        email: ''
      },
      // 表单验证规则
      formRules: {
        id: [
          { required: true, message: '请输入学号', trigger: 'blur' },
          { pattern: /^\d{8,12}$/, message: '学号格式不正确', trigger: 'blur' }
        ],
        name: [
          { required: true, message: '请输入姓名', trigger: 'blur' },
          { min: 2, max: 20, message: '姓名长度为2-20个字符', trigger: 'blur' }
        ],
        gender: [
          { required: true, message: '请选择性别', trigger: 'change' }
        ],
        grade: [
          { required: true, message: '请选择年级', trigger: 'change' }
        ],
        major: [
          { required: true, message: '请选择专业', trigger: 'change' }
        ],
        className: [
          { required: true, message: '请输入班级', trigger: 'blur' }
        ],
        email: [
          { required: true, message: '请输入邮箱', trigger: 'blur' },
          { type: 'email', message: '请输入正确的邮箱格式', trigger: 'blur' }
        ]
      },
      // 选项数据
      gradeOptions: [
        { value: '2020', label: '2020级' },
        { value: '2021', label: '2021级' },
        { value: '2022', label: '2022级' },
        { value: '2023', label: '2023级' }
      ],
      majorOptions: [
        { value: '计算机科学与技术', label: '计算机科学与技术' },
        { value: '软件工程', label: '软件工程' },
        { value: '人工智能', label: '人工智能' },
        { value: '数据科学与大数据技术', label: '数据科学与大数据技术' },
        { value: '网络空间安全', label: '网络空间安全' }
      ],
      fetchError: false
    }
  },
  mounted() {
    this.fetchStudentList()
  },
  methods: {
    // 重试获取数据
    retryFetch() {
      this.fetchError = false
      this.fetchStudentList()
    },

    // 获取学生列表
    async fetchStudentList() {
      this.loading = true
      this.fetchError = false
      
      try {
        const params = {
          page: this.pagination.page,
          pageSize: this.pagination.pageSize,
          ...this.searchForm
        }
        const res = await getStudentList(params)
        if (res && res.status === 200) {
          this.studentList = res.data.list || []
          this.pagination.total = res.data.total || 0
        } else {
          this.fetchError = true
          this.studentList = []
          this.pagination.total = 0
          this.$message.warning('未获取到学生数据')
        }
      } catch (error) {
        console.error('获取学生列表失败:', error)
        this.fetchError = true
        this.$message.error('获取学生列表失败')
        this.studentList = []
        this.pagination.total = 0
      } finally {
        this.loading = false
      }
    },

    // 搜索处理
    handleSearch() {
      this.pagination.page = 1
      this.fetchStudentList()
    },

    // 重置搜索
    resetSearch() {
      this.searchForm = {
        keyword: '',
        grade: '',
        major: ''
      }
      this.handleSearch()
    },

    // 分页处理
    handleSizeChange(size) {
      this.pagination.pageSize = size
      this.fetchStudentList()
    },
    handleCurrentChange(page) {
      this.pagination.page = page
      this.fetchStudentList()
    },

    // 新增学生
    handleAdd() {
      this.isEdit = false
      this.dialogTitle = '新增学生'
      this.formData = {
        id: '',
        name: '',
        gender: 'M',
        grade: '',
        major: '',
        className: '',
        email: ''
      }
      this.dialogVisible = true
      this.$nextTick(() => {
        this.$refs.studentForm && this.$refs.studentForm.clearValidate()
      })
    },

    // 编辑学生
    handleEdit(row) {
      this.isEdit = true
      this.dialogTitle = '编辑学生'
      this.formData = JSON.parse(JSON.stringify(row))
      this.dialogVisible = true
      this.$nextTick(() => {
        this.$refs.studentForm && this.$refs.studentForm.clearValidate()
      })
    },

    // 删除学生
    handleDelete(row) {
      this.$confirm('确定要删除该学生吗？删除后将无法恢复!', '警告', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(async () => {
        this.loading = true
        try {
          const res = await deleteStudent(row.id)
          if (res && res.status === 200) {
            this.$message.success('删除成功')
            this.fetchStudentList()
          } else {
            this.$message.error(res.message || '删除失败')
          }
        } catch (error) {
          console.error('删除学生失败:', error)
          this.$message.error('删除学生失败，请稍后重试')
        } finally {
          this.loading = false
        }
      }).catch(() => {})
    },

    // 提交表单
    submitForm() {
      this.$refs.studentForm.validate(async (valid) => {
        if (valid) {
          this.loading = true
          try {
            const reqData = JSON.parse(JSON.stringify(this.formData))
            
            const res = await saveOrUpdateStudent(reqData)
            
            if (res && res.status === 200) {
              this.$message.success(this.isEdit ? '更新成功' : '新增成功')
              this.dialogVisible = false
              this.fetchStudentList()
            } else {
              this.$message.error(res.message || (this.isEdit ? '更新失败' : '新增失败'))
            }
          } catch (error) {
            console.error(`${this.isEdit ? '更新' : '新增'}学生失败:`, error)
            this.$message.error(`${this.isEdit ? '更新' : '新增'}学生失败，请稍后重试`)
          } finally {
            this.loading = false
          }
        } else {
          return false
        }
      })
    },

    // 查看已选课程
    async handleViewCourses(row) {
      this.currentStudentId = row.id
      this.coursesDialogVisible = true
      this.selectedCourses = []  // 清空之前的数据
      
      this.loading = true  // 显示加载状态
      try {
        const res = await getStudentCourses(row.id)
        if (res && res.status === 200) {
          this.selectedCourses = res.data || []
          if (this.selectedCourses.length === 0) {
            this.$message.info('该学生暂无已选课程')
          }
        } else {
          this.selectedCourses = []
          this.$message.warning(res.message || '未查询到已选课程')
        }
      } catch (error) {
        console.error('获取已选课程失败:', error)
        this.$message.error('获取已选课程失败，请稍后重试')
        this.selectedCourses = []
      } finally {
        this.loading = false
      }
    },

    // 退选课程
    handleCancelCourse(course) {
      this.$confirm('确定要退选该课程吗？', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(async () => {
        this.loading = true
        try {
          const reqData = {
            studentId: this.currentStudentId,
            courseId: course.courseId
          }
          const res = await cancelCourse(reqData)
          if (res && res.status === 200) {
            this.$message.success('退选成功')
            
            // 刷新已选课程列表
            const updatedCourses = this.selectedCourses.filter(c => c.courseId !== course.courseId)
            this.selectedCourses = updatedCourses
            
            // 更新主列表中的已选课程数
            this.fetchStudentList()
          } else {
            this.$message.error(res.message || '退选失败')
          }
        } catch (error) {
          console.error('退选课程失败:', error)
          this.$message.error('退选课程失败，请稍后重试')
        } finally {
          this.loading = false
        }
      }).catch(() => {})
    },
    
    // 跳转到详情页面
    toDetails(id) {
      this.$router.push({
        path: "/sc/student/Details",
        query: { id: id }
      })
    }
  }
}
</script>

<style lang="scss" scoped>
.student-management {
  padding: 20px;
  background-color: #ffffff;
  border-radius: 4px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
}

.control-panel {
  margin-bottom: 20px;
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
}

.search-bar {
  display: flex;
  margin-bottom: 10px;

  .el-input {
    width: 220px;
    margin-right: 10px;
  }
  
  .el-button {
    margin-right: 10px;
  }
}

.filter-options {
  display: flex;

  .el-select {
    width: 150px;
    margin-right: 10px;
  }
}

.pagination-container {
  margin-top: 20px;
  display: flex;
  justify-content: flex-end;
}
</style>
>>>>>>> e4ff8b09d965ebdc39d2a60ba2b577c11b3444d5
